package com.encapi.framework.resolver;

import com.encapi.framework.annotation.DecryptEntity;
import com.encapi.framework.core.CryptManager;
import com.encapi.framework.exception.ExceptionUtil;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.InvocationTargetException;

public class DecEntityHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {

    @Resource
    private CryptManager cryptManager;

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.hasParameterAnnotation(DecryptEntity.class);
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
                                  NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        // 获取 HttpServletRequest
        HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
        if (request == null) {
            return null;
        }

        // 重新改参数对象赋值
        Object instance = methodParameter.getParameterType().newInstance();
        if (instance != null) {
            nativeWebRequest.getParameterMap().forEach((k, v) -> {
                if (v.length != 0) {
                    String strBody = v[0]
                            .replaceAll(" ", "+");
                    String decVal = cryptManager.decrypt(strBody, request, null);
                    try {
                        BeanUtils.setProperty(instance, k, decVal);
                    } catch (IllegalAccessException | InvocationTargetException e) {
                        throw ExceptionUtil.buildDecryptEx(
                                "decrypted request body params failure. cause by {}.", e.getMessage(), e.getCause());
                    }
                }
            });
        }
        return instance;
    }

}
